package org.bing.engine.common.process;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Timer;

import org.bing.engine.common.logging.Log;
import org.bing.engine.common.logging.LogFactory;

public class ProcessReader extends Thread {
    protected static final Log logger = LogFactory.getLog(ProcessReader.class);
    protected static final int LEVEL_INFO = 0;
    protected static final int LEVEL_ERROR = 1;
    private List<InstreamItem> list = new ArrayList<InstreamItem>();

    public synchronized void addInputStream(String guid, InputStream ins) {
        list.add(new InstreamItem(guid, ins, LEVEL_INFO));
    }

    public synchronized void addErrorStream(String guid, InputStream ins) {
        list.add(new InstreamItem(guid, ins, LEVEL_ERROR));
    }

    @Override
    public synchronized void start() {
        // set to daemon
        setDaemon(true);
        // start timer
        startTimer();
        // do main loop to read
        while (true) {
            for (int i = 0, len = list.size(); i < len; i++) {
                try {
                    doRead(list.get(i));
                } catch (IOException ioe) {
                    logger.error("IOException", ioe);
                } catch (InterruptedException ite) {
                    logger.error("InterruptedException", ite);
                } catch (Exception e) {
                    logger.error("Exception", e);
                }
            }
        }
    }

    protected synchronized void startTimer() {
        Timer timer = new Timer("bing-process-single-reader", true);
        timer.schedule(new ProcessNotify(this), 0, 500);
    }

    protected synchronized void doRead(InstreamItem item) throws IOException, InterruptedException {
        InputStream ins = item.input;
        byte[] buf = new byte[1024];
        int len = ins.read(buf);
        while (len > 0) {
            if (item.level == LEVEL_INFO) {
                logger.info(item.guid + " " + new String(buf, 0, len));
            } else if (item.level == LEVEL_ERROR) {
                logger.error(item.guid + " " + new String(buf, 0, len));
            }

            len = ins.read(buf);
        }
    }

    protected class InstreamItem {
        protected String guid;
        protected InputStream input;
        protected int level;

        InstreamItem(String guid, InputStream ins, int level) {
            this.guid = guid;
            this.input = ins;
            this.level = level;
        }
    }

}
